package com.pkche.core.advanced;

import java.util.ArrayList;
import java.util.List;

import com.pkche.core.advanced.model.BaseIncrementIdModel;


/**
 * 批量保存实体操作类
 * <p>
 * 	该类用于处理一个动作可能包含多个操作（删除、修改和新增）的业务操作，调用{@link #process(BaseBiz)}方法处理，可以通过相应属性的get方法，获取处理结果。
 * </p>
 *
 */
public class BatchOperate<T extends BaseIncrementIdModel> {
	/**
	 * 需要保存的实体，该列表包含新增和修改的实体
	 */
	private List<T> saveEntities;
	/**
	 * 要更新的实体，该列表仅包含更新的实体
	 */
	private List<T> updateEntities;
	/**
	 * 新增的实体，该列表仅包含新增的实体
	 */
	private List<T> addEntities;
	/**
	 * 删除的实体，需要删除的实体ID
	 */
	private List<T> removeEntities;
	
	private List<Long> removeIds;
	/**
	 * 构造一个空的实体
	 */
	public BatchOperate(){
	}
	/**
	 * 类构造一个实体
	 * <p>
	 * 	使用此构造方法构造时，请务必使用{@link #setRemoveEntitiesByEntities(java.util.List)}、 {@link #setRemoveEntitiesByIds(java.util.List)}或 {@link #setRemoveEntities(java.util.List)}来设置需要删除的值列表，否则默认为没有需要删除的数据
	 * </p>
	 * @param saveEntities 需要批量操作的实体
	 */
	public BatchOperate(List<T> saveEntities){
		this.saveEntities = saveEntities;
	}
	/**
	 * 构造一个操作实体
	 * @param saveEntities 需要保存的实体
	 * @param removeEntities 移除的实体
	 */
	public BatchOperate(List<T> saveEntities,List<T> removeEntities){
		this.saveEntities = saveEntities;
		this.removeEntities = removeEntities;
	}
	/**
	 * 获取要保存的实体列表，该列表应包含新增和修改的实体
	 * @return 保存的实体列表
	 */
	public List<T> getSaveEntities() {
		return saveEntities;
	}
	/**
	 * 设置要保存的实体列表，该列表应包含新增和修改的实体
	 * @param saveEntities 要保存的实体列表
	 */
	public void setSaveEntities(List<T> saveEntities) {
		this.saveEntities = saveEntities;
	}
	/**
	 * 获取需要更新的实体
	 * @return 实体列表
	 */
	public List<T> getUpdateEntities() {
		return updateEntities;
	}
	/**
	 * 设置需要更新的实体列表
	 * @param updateEntities 实体列表
	 */
	public void setUpdateEntities(List<T> updateEntities) {
		this.updateEntities = updateEntities;
	}
	/**
	 * 设置需要新增的实体列表
	 * @return 新增的实体列表
	 */
	public List<T> getAddEntities() {
		return addEntities;
	}
	/**
	 * 设置需要新增的实体列表
	 * @param addEntities 实体列表
	 */
	public void setAddEntities(List<T> addEntities) {
		this.addEntities = addEntities;
	}
	/**
	 * 获取需要删除的实体列表
	 * @return 列表
	 */
	public List<T> getRemoveEntities() {
		return removeEntities;
	}
	/**
	 * 设置需要删除的实体列表
	 * @param removeEntities 列表值
	 */
	public void setRemoveEntities(List<T> removeEntities) {
		this.removeEntities = removeEntities;
	}
	
	/**
	 * 获取移除的实体编号列表
	 * @return 实体编号列表
	 */
	public List<Long> getRemoveIds() {
		return removeIds;
	}
	/**
	 * 设置需要移除的实体编号列表
	 * @param removeIds 需要移除的实体编号列表
	 */
	public void setRemoveIds(List<Long> removeIds) {
		this.removeIds = removeIds;
	}
	/**
	 * 根据原始数据计算需要删除的数据列表，该参数为实体列表
	 * <p>
	 * 	调用该方法进行重写设置要移除的列表，该方法会用{@link #getSaveEntities()}中查找不存在的列表，并设置进入需要删除的列表中
	 * </p>
	 * @param sources 原始数据
	 */
	public void setRemoveEntitiesByEntities(List<T> sources){
		removeEntities = new ArrayList<T>();
		if(sources != null){
			//检查需要保存的列表不存在，即全部删除
			if(saveEntities == null){
				T entity = null;
				for(int i = 0;i < sources.size();i ++){
					entity = sources.get(i);
					if(entity.getId() != null){
						removeEntities.add(entity);
					}
				}
			}else{
				T entity = null;
				T t = null;
				//开始逐个检查是否存在
				for(int i = 0;i < sources.size();i ++){
					entity = sources.get(i);
					for(int j = 0;j < saveEntities.size();j ++){
						t = saveEntities.get(j);
						//如果存在
						if(t.getId() != null && entity.getId().longValue() == t.getId().longValue()){
							break;
						}
						t = null;
					}
					//如果不存在
					if(t == null){
						removeEntities.add(entity);
					}
				}
			}
		}
	}
	
	/**
	 * 根据原始数据计算需要删除的数据列表，该参数为id列表
	 * <p>
	 * 	调用该方法进行重写设置要移除的列表，该方法会用{@link #getSaveEntities()}中查找不存在的列表，并设置进入需要删除的列表中
	 * </p>
	 * @param sources 原始数据
	 */
	public void setRemoveEntitiesByIds(List<Long> sources){
		removeIds = new ArrayList<Long>();
		if(sources != null){
			//检查需要保存的列表不存在，即全部删除
			if(saveEntities == null){
				for(int i = 0;i < sources.size();i ++){
					removeIds.add(sources.get(i));
				}
			}else{
				Long id = null;
				T t = null;
				//开始逐个检查是否存在
				for(int i = 0;i < sources.size();i ++){
					id = sources.get(i);
					for(int j = 0;j < saveEntities.size();j ++){
						t = saveEntities.get(j);
						//如果存在
						if(t.getId() != null && id.longValue() == t.getId().longValue()){
							break;
						}
						t = null;
					}
					//如果不存在
					if(t == null){
						removeIds.add(id);
					}
				}
			}
		}
	}
	/**
	 * 从saveEntities列表中计算新增和更新的实体列表
	 */
	public void countUpdateOrAdd(){
		addEntities = new ArrayList<T>();
		updateEntities = new ArrayList<T>();
		if(saveEntities != null){
			T entity = null;
			for(int i = 0;i < saveEntities.size();i ++){
				entity = saveEntities.get(i);
				//如果是新增
				if(entity.getId() == null){
					addEntities.add(entity);
				}
				//修改
				else{
					updateEntities.add(entity);
				}
			}
		}
	}
	/**
	 * 处理，即增删该操作处理
	 */
	public void process(BaseBiz<T,? extends BaseDao<T>> baseBiz){
		if(baseBiz == null){
			throw new IllegalArgumentException("baseBiz 不能为空");
		}
		//删除ID列表
		if(removeIds != null){
			baseBiz.deleteByIds(removeIds);
		}
		//删除实体列表
		if(removeEntities != null){
			for(int i = 0;i < removeEntities.size();i ++){
				baseBiz.delete(removeEntities.get(i));
			}
		}
		//如果未计算
		if(addEntities == null){
			countUpdateOrAdd();
		}
		//保存
		if(saveEntities != null){
			T entity = null;
			for(int i = 0;i < saveEntities.size();i ++){
				entity = saveEntities.get(i);
				baseBiz.save(entity);
			}
		}
	}
}
